#include <sdk.h>
#include <wx/xrc/xmlres.h>
#include "sc_base_types.h"

namespace ScriptBindings {
  class XrcDialog : public wxScrollingDialog {
      DECLARE_EVENT_TABLE()
      wxString m_CallBack;
    public:
      XrcDialog( wxWindow* parent, const wxString& dlgName, const wxString& callback ) : m_CallBack( callback ) {
        if( !wxXmlResource::Get()->LoadDialog( this, parent, dlgName ) && !wxXmlResource::Get()->LoadObject( this, parent, dlgName, _T( "wxScrollingDialog" ) ) ) {
          m_Throw( wxEmptyString );
        }
      }
      ~XrcDialog() { }
      void OnButton( wxCommandEvent& event );
  };

  XrcDialog* s_ActiveDialog = nullptr;

  BEGIN_EVENT_TABLE( XrcDialog, wxScrollingDialog )
    EVT_CHOICE( -1, XrcDialog::OnButton )
    EVT_COMBOBOX( -1, XrcDialog::OnButton )
    EVT_CHECKBOX( -1, XrcDialog::OnButton )
    EVT_LISTBOX( -1, XrcDialog::OnButton )
    EVT_RADIOBOX( -1, XrcDialog::OnButton )
    EVT_BUTTON( -1, XrcDialog::OnButton )
  END_EVENT_TABLE()

  void XrcDialog::OnButton( wxCommandEvent& event ) {
    event.Skip( true );
    try {
      SqPlus::SquirrelFunction<void> cb( cbU2C( m_CallBack ) );
      if( cb.func.IsNull() ) {
        return;
      }
      cb( event.GetId() );
    } catch( SquirrelError& e ) {
      Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    }
  }

  int ShowDialog( const wxString& xrc, const wxString& dlgName, const wxString& callback ) {
    wxString actual = ConfigManager::LocateDataFile( xrc, sdScriptsUser | sdScriptsGlobal );
    Manager::Get()->GetLogManager()->Log( _T( "加载 XRC: " ) + actual );
    if( wxXmlResource::Get()->Load( actual ) ) {
      XrcDialog* old = s_ActiveDialog;
      try {
        s_ActiveDialog = new XrcDialog( nullptr, dlgName, callback );
        int ret = s_ActiveDialog->ShowModal();
        delete s_ActiveDialog;
        s_ActiveDialog = old;
        wxXmlResource::Get()->Unload( actual );
        return ret;
      } catch( M_Code_Exception& e ) {
        msging( F( _T( "Dialog \"%s\" 找不到...\n\n实际资源: \"%s\"\n原始资源: \"%s\"" ),
                   dlgName.c_str(), actual.c_str(), xrc.c_str() ),
                _T( "错误" ), wxICON_ERROR );
      }
    } else
    { Manager::Get()->GetLogManager()->Log( _T( "加载 XRC: '" ) + actual + _T( "' FAILED!" ) ); }
    return -1;
  }

  void EndModal( int retCode ) {
    if( s_ActiveDialog ) {
      s_ActiveDialog->EndModal( retCode );
      return;
    }
    msging( _T( "EndModal() 仅在 ShowDialog() 中有效..." ), _T( "错误" ), wxICON_ERROR );
  }

  SQInteger XrcId( HSQUIRRELVM v ) {
    StackHandler sa( v );
    if( !s_ActiveDialog ) {
      msging( _T( "XRCID() 仅在 ShowDialog() 中有效..." ), _T( "错误" ), wxICON_ERROR );
      return sa.Return( ( SQInteger ) - 1 );
    }
    wxWindow* win = nullptr;
    if( sa.GetType( 2 ) == OT_STRING ) {
      win = wxWindow::FindWindowByName( cbC2U( sa.GetString( 2 ) ), s_ActiveDialog );
    } else
    { win = wxWindow::FindWindowByName( *SqPlus::GetInstance<wxString, false>( v, 2 ), s_ActiveDialog ); }
    return sa.Return( ( SQInteger )( win ? win->GetId() : -1 ) );
  }

  void Register_Dialog() {
    SqPlus::RegisterGlobal( ShowDialog, "ShowDialog" );
    SqPlus::RegisterGlobal( EndModal, "EndModal" );
    SquirrelVM::CreateFunctionGlobal( XrcId, "XRCID", "*" );
  }
}
